//------------------------------------------------------------------------------
// X2TK Graphic Toolkit
// Copyright (C) 2006-2007 Janusz Kowalski
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------

#include <queue>

#include "x2tk.h"
#include "RawVector.h"
#include "global.h"
#include "pmsg.h"

namespace x2tk {

static Font *fontActive_=0;
static Font *fontNormal_=0;
static Font *fontDisabled_=0;

void init() {
  fontActive_ = new Font(X2D_PATH_DATA "HiTechFont_White.png");
  fontNormal_ = new Font(X2D_PATH_DATA "HiTechFont_Black.png");
  // !! Should be gray or something.
  fontDisabled_ = new Font(X2D_PATH_DATA "HiTechFont_Black.png");
}

void done() {
  delete fontActive_;
  delete fontNormal_;
  delete fontDisabled_;
}

static Uint32 XColor[] = {
  0xD4AA00FF, 0x808080FF, 0xCCCCCCFF,
  0xCCCCCCFF, 0xE6E6E6FF, 0xF2F2F2FF
};

Uint32 getColor(int id) {
  return XColor[id];
}

const Font* getFont(int id) {
  switch(id) {
    case FONT_ACTIVE:
      return fontActive_; break;
    case FONT_NORMAL:
      return fontNormal_; break;
    case FONT_DISABLED:
      return fontDisabled_; break;
    default:
      return 0;
  }
}

static Sint16 vx[6];
static Sint16 vy[6];

void drawBox(GraphicContext& g, Uint32 bg, Uint32 fg) {
//   int w=g.getW();
//   
//   for(int y=0; y<100; y++) {
//     g.hLine(0,w,y,fg);
//   }
/*

  // !! Should have correct values.
  int w=g.getW(), h=g.getH();
  
  // Prepare data.
  vx[0]=0;     vy[0]=4;
  vx[1]=4;     vy[1]=0;
  vx[2]=w-1;   vy[2]=0;
  vx[3]=w-1;   vy[3]=h-1-4;
  vx[4]=w-1-4; vy[4]=h-1;
  vx[5]=0;     vy[5]=h-1;
  
  // Draw it.
  g.filledPolygon(vx,vy,6,bg);*/
}


struct CallInfo {
  Widget *w;
  int id;
  bool isEvent;
};

static std::deque<CallInfo> callQueue;

void callLater(Widget *w, int id) {
  CallInfo cinfo = {w, id, false};
  callQueue.push_back(cinfo);
}

// !! This should be changed. Event ID is not integer.
void pushEvent(Widget *w, int id) {
  CallInfo cinfo = {w, id, true};
  callQueue.push_back(cinfo);
}

static RawVector<CallInfo> callVec;

void callRepetitively(Widget *w, int id) {
  CallInfo cinfo = {w,id};
  callVec.add(cinfo);
}

void cancelRepetitiveCalls(Widget *w) {
  for(int i=callVec.size(); i--;) {
    if(callVec[i].w==w) callVec[i].w=0;
  }
}

void doCalls() {
  // Call fuunctions from the queues.
  while(!callQueue.empty()) {
    CallInfo cinfo = callQueue.front(); callQueue.pop_front();
    if(cinfo.w!=0) {
      if(cinfo.isEvent) cinfo.w->event((EV)cinfo.id);
      else cinfo.w->timed(cinfo.id);
    }
  }
  
  // Call repetitive functions.
  for(int i=callVec.size(); i--;) {
    CallInfo &cinfo = callVec[i];
    if(cinfo.w!=0) cinfo.w->timed(cinfo.id);
  }
  
  // Remove cancelled repetitive function calls.
  for(int i=callVec.size(); i--;) {
    if(callVec[i].w==0) callVec.removeElementAt(i);
  }
}

void cancelCalls(Widget *w) {
  // Cancel queued calls.
  for(int i=callQueue.size(); i--;) {
    if(callQueue[i].w==w) callQueue[i].w=0;
  }
  
  // Cancel repetitive calls.
  cancelRepetitiveCalls(w);
  
  pmsgDebugF("Call to %p cancelled\n", w);
}

} // namespace x2tk
